package com.boss.salary.controller;

import com.boss.api.dto.ApiResultDTO;
import com.boss.common.base.BasicinfoBaseController;
import com.boss.common.entity.PageDTO;
import com.boss.common.service.ICommonService;
import com.boss.common.util.PageUtils;
import com.boss.framework.dto.PaginationDTO;
import com.boss.framework.exception.AppRuntimeException;
import com.boss.salary.dto.PaymentSendDTO;
import com.boss.salary.entity.MakeSalaryData;
import com.boss.salary.entity.OperrateLogs;
import com.boss.salary.entity.SalaryPaymentRequisitionBack;
import com.boss.salary.service.IGenerateSalaryDataService;
import com.boss.salary.service.IOperrateLogsService;
import com.boss.salary.service.IPaymentAsyncService;
import com.boss.salary.service.IRedisService;
import com.boss.salary.vo.SalaryDataVo;
import com.boss.sys.ca.user.dto.UserDTO;
import com.boss.sys.utils.SysUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/generateSalaryDataController")
public class GenerateSalaryDataController extends BasicinfoBaseController {

    /**
     * 引入日志框架常量
     */
    private final static Logger logger = LoggerFactory.getLogger(GenerateSalaryDataController.class);

    @Autowired
    private IGenerateSalaryDataService iGenerateSalaryDataService;

    @Autowired
    private ICommonService iCommonService;

    @Autowired
    private IOperrateLogsService iOperrateLogsService;
    @Autowired
    private IRedisService redisService;
    @Autowired
    private IPaymentAsyncService paymentAsyncService;
    /**
     * 获取工资数据分页
     * @param page
     * @param limit
     * @return
     */
    @GetMapping("/queryGenerateSalaryDataPage")
    public ApiResultDTO queryGenerateSalaryDataPage(@RequestHeader("X-Token") String tokenid,
                                                    @RequestParam(value = "page") String page,
                                                    @RequestParam(value = "limit") String limit,
                                                    @RequestParam(value = "flag") String flag,
                                                    @RequestParam(value = "menuid") String menuid,
                                                    @RequestParam(value = "salaryType") String salaryType,
                                                    @RequestParam(value = "changeAgency") String changeAgency,
                                                    @RequestParam(value = "agencyId") String agencyId,
                                                    @RequestParam(value = "salaCardBank") String salaCardBank) {
        try {
            UserDTO userDto = getUser(tokenid);

            List<String> childrenId = iCommonService.getAgencyChildrenId(userDto, agencyId,tokenid);
            Map<String, Object> queryParam = new HashMap<>(3);
            queryParam.put("flag", flag);
            queryParam.put("salaryType", salaryType);
            queryParam.put("changeAgency", changeAgency);
            queryParam.put("menuid", menuid);
            queryParam.put("agencyId", agencyId);
            queryParam.put("salaCardBank", salaCardBank);
            PaginationDTO paginationDTO = PageUtils.buildPaginationDTOPage(page,limit);
            PageDTO<SalaryDataVo> pageDTO = iGenerateSalaryDataService.queryGenerateSalaryDataPage(userDto,paginationDTO, queryParam, childrenId,tokenid);
            return ApiResultDTO.success(pageDTO);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return ApiResultDTO.error(ERROR_RSCODE, "查询数据异常");
        }
    }


    /**
     * 生成工资数据
     * @param tokenid
     * @param makeSalaryData 要生成工资数据的单位
     * @return
     */
    @PostMapping("/makeSalaryDataAsync")
    public ApiResultDTO makeSalaryDataAsync(@RequestHeader("X-Token") String tokenid,
                                       @RequestBody MakeSalaryData makeSalaryData){
        try {
            UserDTO userDto = getUser(tokenid);
            Object re=redisService.get(userDto.getProvince()+"generateSalary");
            //查询缓存中该区划是否有在执行的生成操作
            String uuid=userDto.getProvince()+"generateSalaryPercent";
            if(!SysUtils.isNullOrEmpty(re)){
                Map<String,String> map=new HashMap<>();
                Object message=redisService.get(userDto.getProvince()+"generateSalaryMessage");
                map.put("message","已在生成中,请勿重复操作"+(SysUtils.isNullOrEmpty(message)?"":message.toString()));
                map.put("guid",uuid);
                map.put("messageKey",userDto.getProvince()+"generateSalaryMessage");
                Object generateSalarySend=redisService.get(userDto.getProvince()+"generateSalarySend");
                if(!SysUtils.isNullOrEmpty(generateSalarySend)){
                    Map<String,String> generateSalarySendMap= (Map<String, String>) generateSalarySend;
                    map.put("agencyCount", generateSalarySendMap.get("agencyCount"));
                    map.put("personCount",generateSalarySendMap.get("personCount"));
                    map.put("sumRealSalary",generateSalarySendMap.get("sumRealSalary"));
                }else {
                    map.put("agencyCount", makeSalaryData.getAgencyCount());
                    map.put("personCount", makeSalaryData.getPersonCount());
                    map.put("sumRealSalary", makeSalaryData.getSumRealSalary());
                }
                return ApiResultDTO.success(map);
            }
            Map<String,String> generateSalarySend=new HashMap<>();
            generateSalarySend.put("agencyCount",makeSalaryData.getAgencyCount());
            generateSalarySend.put("personCount",makeSalaryData.getPersonCount());
            generateSalarySend.put("sumRealSalary",makeSalaryData.getSumRealSalary());
            redisService.put(userDto.getProvince()+"generateSalarySend",generateSalarySend);
            redisService.put(userDto.getProvince()+"generateSalary", 1);//添加执行控制，避免重复操作
            redisService.put(uuid, "0");
            //添加操作日志
            OperrateLogs operrateLogs= new OperrateLogs();
            operrateLogs.setMofDivCode(userDto.getProvince());
            operrateLogs.setTokenId(tokenid);
            operrateLogs.setUserAgencyId(userDto.getAgency());
            operrateLogs.setUeserName(userDto.getName());
            operrateLogs.setOperateName("生成工资数据--生成支付数据--生成");
            iOperrateLogsService.saveOperrateLogs(operrateLogs);

            Map<String,String> map = paymentAsyncService.makeSalaryDataAsyncRedis(tokenid, makeSalaryData,userDto);
            return ApiResultDTO.success(map);

        } catch (AppRuntimeException e) {
            e.printStackTrace();
            logger.error("生成工资数据失败", e.getMessage());
            return ApiResultDTO.error(ERROR_RSCODE, e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("生成工资数据失败", e.getMessage());
            return ApiResultDTO.error(ERROR_RSCODE, e.getMessage());
        }
    }


    /**
     * 检测生成工资的数据
     * @param tokenid
     * @param makeSalaryData 要生成工资数据的单位
     * @return
     */
    @PostMapping("/checkSalaryData")
    public ApiResultDTO checkSalaryData(@RequestHeader("X-Token") String tokenid,
                                            @RequestBody MakeSalaryData makeSalaryData){
        try {
            UserDTO userDto = getUser(tokenid);
            Map<String,Object> map =iGenerateSalaryDataService.checkSalaryData(tokenid, makeSalaryData,userDto);
            return ApiResultDTO.success(map);

        } catch (AppRuntimeException e) {
            e.printStackTrace();
            logger.error("检测生成工资数据失败", e.getMessage());
            return ApiResultDTO.error(ERROR_RSCODE, e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("检测生成工资数据失败", e.getMessage());
            return ApiResultDTO.error(ERROR_RSCODE, e.getMessage());
        }
    }


    @PostMapping("/pushSalaryDataByPostman")
    public ApiResultDTO pushSalaryDataByPostman(@RequestHeader("X-Token") String tokenid,
                                                @RequestBody PaymentSendDTO paymentSendDTO){
        try {
            UserDTO userDto = getUser(tokenid);
            logger.info("手动推送支付数据", paymentSendDTO.toString());
            paymentAsyncService.postManToPayment(paymentSendDTO.getPaymentList(), paymentSendDTO.getAccountList(),userDto,tokenid,paymentSendDTO.getAgencyIds());
            return ApiResultDTO.success();

        } catch (AppRuntimeException e) {
            e.printStackTrace();
            logger.error("手动推送支付数据失败", e.getMessage());
            return ApiResultDTO.error(ERROR_RSCODE, e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("手动推送支付数据失败", e.getMessage());
            return ApiResultDTO.error(ERROR_RSCODE, e.getMessage());
        }
    }

    /**
     * 查看支付生成进度
     * @param uuid
     * @return
     */
    @GetMapping("/getPaymentPercent")
    public ApiResultDTO  getPaymentPercent(@RequestParam(value = "uuid") String uuid,@RequestHeader("X-Token") String tokenid){
        try {
            UserDTO userDto = getUser(tokenid);
            Object re = redisService.get(uuid);

            if ("S".equals(re) || (re != null && re.toString().startsWith("F"))) {
                redisService.del(uuid);
                Object generateSalaryState = redisService.get(userDto.getProvince() + "generateSalary");
                if(generateSalaryState!=null) {
                    redisService.del(userDto.getProvince() + "generateSalary");
                }
            }
            return ApiResultDTO.success(re);
        }catch (Exception e) {
                e.printStackTrace();
                logger.error("检测生成工资数据失败", e.getMessage());
                return ApiResultDTO.error(ERROR_RSCODE, e.getMessage());
        }
    }

    /**
     * 获取单位银行上传状态
     * @return
     */
    @GetMapping("/getBankDataStatus")
    public ApiResultDTO getBankDataStatus(@RequestParam("agencyIds") List<String> agencyIds) {
        try {
            boolean status = iGenerateSalaryDataService.getBankDataStatus(agencyIds);
            return ApiResultDTO.success(status);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("撤销支付失败", e.getMessage());
            return ApiResultDTO.error(ERROR_RSCODE, "获取银行上传状态失败");
        }
    }

    /**
     * 撤销支付
     * @param tokenid
     * @return
     */
    @PostMapping("/revokeSalaryData")
    public ApiResultDTO revokeSalaryData(@RequestHeader("X-Token") String tokenid,
                                         @RequestBody MakeSalaryData makeSalaryData) {
        try {
            UserDTO userDto = getUser(tokenid);
            //添加操作日志
            OperrateLogs operrateLogs= new OperrateLogs();
            operrateLogs.setMofDivCode(userDto.getProvince());
            operrateLogs.setTokenId(tokenid);
            operrateLogs.setUserAgencyId(userDto.getAgency());
            operrateLogs.setUeserName(userDto.getName());
            operrateLogs.setOperateName("生成工资数据--生成支付数据--撤销生成");
            iOperrateLogsService.saveOperrateLogs(operrateLogs);

            iGenerateSalaryDataService.revokeSalaryData(tokenid, makeSalaryData,userDto);
            return ApiResultDTO.success();
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("已进入支付流程，无法撤销！", e.getMessage());
            return ApiResultDTO.error(ERROR_RSCODE, e.getMessage());
        }
    }

    /**
     * 获取支付回单数据
     * @param agencyId
     * @param salaryMonth
     * @return
     */
    @GetMapping("/getPayBackData")
    public ApiResultDTO getPayBackData(@RequestHeader("X-Token") String tokenid,
                                        @RequestParam("agencyId") String agencyId,
                                       @RequestParam("salaryMonth") String salaryMonth) {
        try {
            UserDTO userDTO=getUser(tokenid);
            Map<String, Object> queryParam = new HashMap<>(2);
            queryParam.put("agencyId", agencyId);
            queryParam.put("salaryMonth", salaryMonth);
            List<SalaryPaymentRequisitionBack> result = iGenerateSalaryDataService.getPayBackData(queryParam,tokenid,userDTO);
            return ApiResultDTO.success(result);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("获取支付回单数据失败", e.getMessage());
            return ApiResultDTO.error(ERROR_RSCODE, "获取支付回单数据失败");
        }
    }




    /**
     * 撤销生成银行文件
     */
    @PostMapping("/revokeGenerate")
    public ApiResultDTO revokeGenerate(@RequestHeader("X-Token") String tokenId) {
        try {
            String province = getUser(tokenId).getProvince();
            iGenerateSalaryDataService.revokeGenerate(province);
            return ApiResultDTO.success("撤销生成成功！");
        } catch (AppRuntimeException e) {
            logger.error(e.getMessage(), e);
            return ApiResultDTO.error(ERROR_RSCODE, e.getMessage());
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return ApiResultDTO.error(ERROR_RSCODE, "重新生成失败！");
        }
    }

    @PostMapping("/backGenerate")
    public ApiResultDTO backGenerate(@RequestHeader("X-token") String tokenId,@RequestBody  List<SalaryPaymentRequisitionBack> paymentRequisitionBacks) {
        try {
            UserDTO userDto = getUser(tokenId);
            Map<String, String> result =iGenerateSalaryDataService.backGenerate(userDto,tokenId,paymentRequisitionBacks);
            if(!"200".equals(result.get("rscode"))){
                return ApiResultDTO.error(ERROR_RSCODE, result.get("result"));
            }
            return ApiResultDTO.success(result.get("result"));
        } catch (AppRuntimeException e) {
            logger.error(e.getMessage(), e);
            return ApiResultDTO.error(ERROR_RSCODE, e.getMessage());
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return ApiResultDTO.error(ERROR_RSCODE, "退回失败！");
        }
    }
    @PostMapping("/pay/workflow")
    public ApiResultDTO payWorkflow(@RequestHeader("X-token") String tokenId,@RequestBody  Map<String,String> payWorkflow)  {
        try {
            UserDTO userDto = getUser(tokenId);
            iGenerateSalaryDataService.payWorkflow(userDto, payWorkflow, tokenId);

            return ApiResultDTO.success();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return ApiResultDTO.error(ERROR_RSCODE, e.getMessage());
        }
    }
}
